home *** CD-ROM | disk | FTP | other *** search
-
- /**************************************************************************************
-
- FILENAME
- OSUtilsSup.c
-
- DESCRIPTION
- A colection of utilities to aid in the patching of traps.
-
- COPYRIGHT
- Copyright © Apple Computer, Inc. 1990
- All rights reserved.
-
- ROUTINES
- EXTERNAL
- PatchTrap
- RestoreTrap
-
- MODIFICATION HISTORY
- 01/05/90 Sean Parent
- 1) Ported from OpSysUtilSup.p and updated with lots of new wizzies.
- 03/04/90 sp
- 1) Moved into Pack2.
- 2) Added check for System 7.0.
-
- **************************************************************************************/
-
- #pragma segment Utilities
- #define Pack2Internal
-
- /**************************************************************************************
-
- INCLUDES
-
- **************************************************************************************/
-
- #ifndef __TYPES__
- #include <Types.h>
- #endif
-
- #ifndef __MEMORY__
- #include <Memory.h>
- #endif
-
- #ifndef __ERRORS__
- #include <Errors.h>
- #endif
-
- #ifndef __TRAPS__
- #include <Traps.h>
- #endif
-
- #ifndef __OSUTILS__
- #include <OSUtils.h>
- #endif
-
- #include "OSUtilsSup.h"
-
- /*<FF>*/
- /**************************************************************************************
-
- TYPEDEFS
-
- **************************************************************************************/
-
-
- short NumToolboxTraps(void)
- {
- if (GetToolboxTrapAddress(_InitGraf) == GetToolboxTrapAddress(0xAA6E)) {
- return 0x0200;
- } else return 0x0400;
- }
-
- TrapType GetTrapType(short theTrap)
- {
- enum { trapMask = 0x0800 };
-
- if (theTrap & trapMask) return ToolTrap;
- else return OSTrap;
- }
-
- Boolean TrapEntryAvailable(short theTrap, TrapType tType)
- {
- /* Note: What about autopop? */
-
- if ((tType == ToolTrap) && ((theTrap & 0x03FF) >= NumToolboxTraps())) return false;
-
- #ifdef oldSupport
-
- /* Is the trap in part of the table that maybe overlayed? */
-
- if (((tType == ToolTrap) && ((theTrap & 0x03FF) < 0x0100)) || (tType == OSTrap)) {
- long address = GetTrapAddress(theTrap, trapType);
-
- /* Is the trap table overlayed or are the traps duplicates and not unimplemented? */
-
- if ((GetToolboxTrapAddress(0xA000) == GetOSTrapAddress(0xA800))
- || ((address == NGetTrapAddress(theTrap, !trapType))
- && (address != GetToolboxTrapAddress(_Unimplemented)))) {
-
- /* Is it a valid trap type */
-
- theTrap &= 0x00FF;
- if (((theTrap < 0x0050) || (theTrap == 0x0054) || (theTrap == 0x0057))
- != (tType == OSTrap)) return false;
- }
- }
- #endif
-
- return true;
- }
-
- Boolean TrapAvailable(short theTrap)
- {
- TrapType tType;
-
- tType = GetTrapType(theTrap);
- if (!TrapEntryAvailable(theTrap, tType)) return false;
- return NGetTrapAddress(theTrap, tType) != GetToolboxTrapAddress(_Unimplemented);
- }
-
- void FlushInstructionRange(void* address, long count)
- {
- #pragma unused (address, count)
-
- FlushInstructionCache();
-
- #if false
- if (TrapAvailable(_HWPriv)) {
- if (FlushCodeCacheRange(address, count) == hwParamErr) {
- FlushInstructionCache();
- }
- } else if (TrapAvailable(_FlushCodeCache)) FlushCodeCache();
- #endif
- }
-
- /*<FF>*/
- /**************************************************************************************
-
- ROUTINE
- PatchTrap
-
- DESCRIPTION
- Given a trap number and a routine address install a patch. If there is no entry in
- the trap table for trap type (older machine) then return nil. The patchType may be
- override and/or removable. If the patch is an override then nil will be returned if
- the routine is already implemented (This is useful to avoid patching a trap twice).
- If the patch is removeable then a reference will be returned to a block that is used
- to unhook the patch on removal. The address of the previouse routine is returned
- in oldRoutine or nil if it was unimplemented.
-
- **************************************************************************************/
-
- #define require(assertion, handler) \
- do { \
- if (assertion) ; else goto handler; \
- } while (false)
-
-
- #define JMP 0x4EF9
-
- Patch PatchTrap( ProcPtr* oldRoutine,
- short theTrap,
- ProcPtr routine,
- PatchType patchType)
- {
- ProcPtr tempRoutine;
- TrapType tType;
-
- tType = GetTrapType(theTrap);
- require(TrapEntryAvailable(theTrap, tType), TrapEntryAvailable);
-
- tempRoutine = (ProcPtr)NGetTrapAddress(theTrap, tType);
-
- if (oldRoutine) *oldRoutine = tempRoutine;
-
- if (*oldRoutine == NGetTrapAddress(_Unimplemented, ToolTrap)) {
- *oldRoutine = nil;
- }
-
- require(!((patchType & patchOverride) && *oldRoutine), TrapImplemented);
-
- if (patchType & patchRemovable) {
- SPatch* patch = (SPatch*)NewPtrSys(sizeof(SPatch));
-
- require(patch, NewSysPtr);
-
- patch->jump = JMP;
- patch->where = routine;
- patch->trap = theTrap;
- patch->routine = *oldRoutine;
-
- FlushInstructionRange(patch, sizeof(SPatch));
-
- NSetTrapAddress((long)patch, theTrap, tType);
- return (Patch)patch;
- } else {
- NSetTrapAddress((long)routine, theTrap, tType);
- return (Patch)-1;
- }
-
- NewSysPtr:
- TrapImplemented:
- TrapEntryAvailable:
- return nil;
- }
-
- /*<FF>*/
- /**************************************************************************************
-
- ROUTINE
- RestoreTrap
-
- DESCRIPTION
- Given a patch as returned by PatchTrap, RestoreTrap will remove the patch.
-
- **************************************************************************************/
-
- void RestoreTrap(Patch patch)
- {
- TrapType trapType = GetTrapType(patch->trap);
-
- /*
- If the trap has been patched then change the jump vector to point to the
- original routine. Otherwise set the trap address to point to the original
- routine and dispose of the patch.
- */
-
- if (NGetTrapAddress(((SPatch*)patch)->trap, trapType) != patch) {
- ((SPatch*)patch)->where = ((SPatch*)patch)->routine;
- FlushInstructionRange(patch, sizeof(SPatch));
- } else {
- NSetTrapAddress((long)patch->routine, ((SPatch*)patch)->trap, trapType);
- DisposePtr((Ptr)patch);
- }
- }